package cn.xuguowen.user.designPatten.chain_of_responsibility.article.function_interface;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * ClassName: ArtiicleCheckComponent
 * Package: cn.xuguowen.user.designPatten.chain_of_responsibility
 * Description:
 *
 * @Author 徐国文
 * @Create 2023/6/2 10:41
 * @Version 1.0
 */
@Component
@Slf4j
public class ArtiicleCheckComponent {
    /**
     * 校验文章：只能校验一篇文章的
     * @param article
     * @return
     */
    public ArticleCheckResult checkArticle(Article article) {
        // 文章上下文对象
        ArticleContext context = new ArticleContext();
        // 校验规则具有顺序 1.校验标题 2.校验内容长度
        return this.checkTitle(article)
                .andThen(this.checkContent(article))
                .apply(context)
                .articleCheckResult();
    }

    /**
     * 校验文章标题
     * @param article
     * @return
     */
    private Function<ArticleContext,ArticleContext> checkTitle(Article article) {
        return buildCheck(titleCheckContext -> {
            if (titleCheckContext.hasError()) {
                return;
            }

            String title = article.getTitle();
            if (title.contains("色情")) {
                this.addFieldMsg(titleCheckContext.articleCheckResult(),"标题不能存在色情二字");
            }
        });
    }

    /**
     * 校验文章内容长度
     * @param article
     * @return
     */
    private Function<ArticleContext,ArticleContext> checkContent(Article article) {
        return buildCheck(titleCheckContext -> {
            if (titleCheckContext.hasError()) {
                return;
            }

            String content = article.getContent();
            if (content.length() > 10) {
                this.addFieldMsg(titleCheckContext.articleCheckResult(),"内容长度不能大于10");
            }
        });
    }

    /**
     * 自定义校验规则，通过传入消费型函数式接口实现的
     * @param checkConsumer
     * @return
     * @param <T>
     */
    private static <T> Function<T, T> buildCheck(Consumer<T> checkConsumer) {
        return checkContext -> {
            checkConsumer.accept(checkContext);
            return checkContext;
        };
    }

    /**
     * 添加错误信息
     * @param articleCheckResult
     * @param msg
     */
    private void addFieldMsg(ArticleCheckResult articleCheckResult,String msg) {
        List<String> failedMsgList = articleCheckResult.getFailedMsgList();
        if (failedMsgList == null) {
            failedMsgList = new ArrayList<>();
            articleCheckResult.setFailedMsgList(failedMsgList);
        }

        failedMsgList.add(msg);
    }
}
